package dingdan

import (
	"errors"
	"fmt"
	"math"
	"server/a"
	"strconv"
	"time"

	"github.com/shopspring/decimal"
)

type S7废留 struct {
}

func (s *S7废留) A图表(cycle string) (S图表, error) {
	switch cycle {
	case "thirtyday":
		return s.予30天()
	case "week":
		return s.予星期()
	case "month":
		return s.予月份()
	case "year":
		return s.予年份()
	default:
		return s.予30天()
	}
}

type S单天订单 struct {
	Day   string          `json:"day"`   // 日期标识（如 "01", "周一", "06-15"）
	Count int             `json:"count"` // 订单数量
	Price decimal.Decimal `json:"price"` // 订单金额
}

type S总计 struct {
	Count int             `json:"count"` // 总订单数
	Price decimal.Decimal `json:"price"` // 总金额
}

type S图表 struct {
	YAxis    YAxisData    `json:"yAxis"`
	Legend   []string     `json:"legend"`
	XAxis    []string     `json:"xAxis"`
	Series   []SeriesItem `json:"series"`
	PreCycle PreCycleData `json:"pre_cycle"`
	Cycle    CycleData    `json:"cycle"`
}

// Y轴最大值
type YAxisData struct {
	MaxNum   int             `json:"maxnum"`   // 最大订单数
	MaxPrice decimal.Decimal `json:"maxprice"` // 最大金额
}

// 图表系列项
type SeriesItem struct {
	Name       string    `json:"name"`
	Type       string    `json:"type"`
	ItemStyle  ItemStyle `json:"itemStyle"`
	Data       any       `json:"data"` // 金额([]decimal.Decimal)或数量([]int)
	YAxisIndex int       `json:"yAxisIndex,omitempty"`
}

// 周期统计数据
type PreCycleData struct {
	Count CycleStat `json:"count"`
	Price CycleStat `json:"price"`
}
type CycleData struct {
	Count CycleDetail `json:"count"`
	Price CycleDetail `json:"price"`
}
type CycleStat struct{ Data int }

type CycleDetail struct {
	Data    int     `json:"data"`
	Percent float64 `json:"percent"`
	IsPlus  int     `json:"is_plus"` // -1:降 0:平 1:增
}

type ItemStyle map[string]any

func 予渐变(colors []string) ItemStyle {
	return ItemStyle{
		"color": map[string]any{
			"x":  0.0,
			"y":  0.0,
			"x2": 0.0,
			"y2": 1.0, // 从上到下渐变
			"colorStops": []map[string]any{
				{"offset": 0.0, "color": colors[0]},
				{"offset": 0.5, "color": colors[1]},
				{"offset": 1.0, "color": colors[2]},
			},
		},
	}
}

func 予蓝色渐变() ItemStyle {
	return 予渐变([]string{"#69cdff", "#3eb3f7", "#1495eb"})
}

func 予绿色渐变() ItemStyle {
	return 予渐变([]string{"#6fdeab", "#44d693", "#2cc981"})
}

func 予增长状态(diff int64) int {
	switch {
	case diff > 0:
		return -1 // 上期 > 当期 → 下降
	case diff < 0:
		return 1 // 上期 < 当期 → 增长
	default:
		return 0 // 持平
	}
}

func 予周期统计差异(pre, current *S总计) (CycleData, error) {
	if pre == nil || current == nil {
		return CycleData{}, errors.New("统计数据不能为空")
	}

	订单数差距 := int64(pre.Count - current.Count)
	preCount := pre.Count
	if preCount == 0 {
		preCount = 1 // 避免除零
	}
	countPercent := math.Round((math.Abs(float64(订单数差距))/float64(preCount)*100)*100) / 100

	// 金额差异
	金额差 := pre.Price.Sub(current.Price).IntPart()
	prePrice := pre.Price
	if prePrice.IsZero() {
		prePrice = decimal.NewFromInt(1)
	}
	pricePercent := math.Round(
		prePrice.Sub(current.Price).Abs().Div(prePrice).Mul(decimal.NewFromInt(100)).InexactFloat64()*100,
	) / 100

	return CycleData{
		Count: CycleDetail{
			Data:    current.Count,
			Percent: countPercent,
			IsPlus:  予增长状态(订单数差距),
		},
		Price: CycleDetail{
			Data:    int(current.Price.IntPart()),
			Percent: pricePercent,
			IsPlus:  予增长状态(金额差),
		},
	}, nil
}

func 补缺失日期(dateKeys []string, dataMap map[string]S单天订单) []S单天订单 {
	filled := make([]S单天订单, 0, len(dateKeys))
	for _, day := range dateKeys {
		if item, ok := dataMap[day]; ok {
			filled = append(filled, item)
		} else {
			filled = append(filled, S单天订单{
				Day:   day,
				Count: 0,
				Price: decimal.Zero,
			})
		}
	}
	return filled
}

func 提取轴数据(items []S单天订单) (xAxis []string, prices []decimal.Decimal, counts []int, maxNum int, maxPrice decimal.Decimal) {
	for _, item := range items {
		xAxis = append(xAxis, item.Day)
		prices = append(prices, item.Price)
		counts = append(counts, item.Count)

		if item.Count > maxNum {
			maxNum = item.Count
		}
		if item.Price.GreaterThan(maxPrice) {
			maxPrice = item.Price
		}
	}
	return
}

func (s *S7废留) 予30天() (res S图表, err error) {
	now := time.Now()
	日期范围 := struct {
		CurrentStart string
		CurrentEnd   string
		PreStart     string
		PreEnd       string
	}{
		CurrentStart: now.AddDate(0, 0, -30).Format("2006-01-02"),
		CurrentEnd:   now.Format("2006-01-02 15:04:05"),
		PreStart:     now.AddDate(0, 0, -60).Format("2006-01-02"),
		PreEnd:       now.AddDate(0, 0, -30).Format("2006-01-02"),
	}

	// 生成30天日期键（mm-dd）
	dateKeys := make([]string, 30)
	for i := range 30 {
		dateKeys[i] = now.AddDate(0, 0, i-29).Format("01-02")
	}

	// 查询并处理数据
	orderList, err := A以时间分组统计(日期范围.CurrentStart, 日期范围.CurrentEnd, "30")
	fmt.Printf("orderList 👉 %+v\n", orderList)
	if err != nil {
		return
	}
	if len(orderList) == 0 {
		return
	}

	// 转换为map便于查询
	orderMap := make(map[string]S单天订单, len(orderList))
	for _, item := range orderList {
		orderMap[item.Day] = item
	}
	filledItems := 补缺失日期(dateKeys, orderMap)
	xAxis, prices, counts, maxNum, maxPrice := 提取轴数据(filledItems)

	// 构建系列
	series := []SeriesItem{
		{
			Name:      "订单金额",
			Type:      "bar",
			ItemStyle: 予蓝色渐变(),
			Data:      prices,
		},
		{
			Name:       "订单数",
			Type:       "line",
			ItemStyle:  予绿色渐变(),
			Data:       counts,
			YAxisIndex: 1,
		},
	}

	// 总统计
	preTotal, _ := A以时间统计(日期范围.PreStart, 日期范围.PreEnd)
	currentTotal, _ := A以时间统计(日期范围.CurrentStart, 日期范围.CurrentEnd)

	cycleDiff, _ := 予周期统计差异(preTotal, currentTotal)

	res = S图表{
		YAxis:    YAxisData{MaxNum: maxNum, MaxPrice: maxPrice},
		Legend:   []string{"订单金额", "订单数"},
		XAxis:    xAxis,
		Series:   series,
		PreCycle: 予上期统计数据(preTotal),
		Cycle:    cycleDiff,
	}
	return
}

type S时间范围 struct {
	Pre     struct{ Start, End string }
	Current struct{ Start, End string }
}

func (s *S7废留) 予星期() (S图表, error) {
	now := time.Now()
	weekday := int(now.Weekday()) // 0-6 对应周日到周六

	// %取余
	今天距星期一天数 := (weekday + 6) % 7
	thisMonday := now.AddDate(0, 0, -今天距星期一天数)

	// 基于本周一计算上周和本周的范围（左闭右开区间）
	上周开始 := thisMonday.AddDate(0, 0, -7).Format("2006-01-02") // 上周一 默认具体时间都是 00:00:00
	上周结束 := thisMonday.Format("2006-01-02")                   // 本周一（不包含）
	本周开始 := thisMonday.Format("2006-01-02")                   // 本周一
	本周结束 := thisMonday.AddDate(0, 0, 7).Format("2006-01-02")  // 下周一（不包含）

	// fmt.Printf("上周开始 (上周一) 👉 %+v\n", 上周开始)
	// fmt.Printf("上周结束 (本周一) 👉 %+v\n", 上周结束)
	// fmt.Printf("本周开始 (本周一) 👉 %+v\n", 本周开始)
	// fmt.Printf("本周结束 (下周一) 👉 %+v\n", 本周结束)

	时间范围 := S时间范围{}
	时间范围.Pre.Start = 上周开始
	时间范围.Pre.End = 上周结束
	时间范围.Current.Start = 本周开始
	时间范围.Current.End = 本周结束

	dayMap := map[int]string{
		0: "周一",
		1: "周二",
		2: "周三",
		3: "周四",
		4: "周五",
		5: "周六",
		6: "周日",
	}

	// 查询数据
	单天订单组, err := A以时间分组统计(时间范围.Current.Start, 时间范围.Current.End, "week")
	if err != nil {
		return S图表{}, err
	}

	// 转换为索引map（数据库返回的是 0-6对应周日到周六）
	单天订单集 := make(map[int]S单天订单)
	for _, item := range 单天订单组 {
		idx, _ := strconv.Atoi(item.Day)
		最终序号 := (idx - 1 + 7) % 7
		if dayName, ok := dayMap[最终序号]; ok {
			item.Day = dayName
		}
		单天订单集[最终序号] = item
	}

	上周单天订单组, err := A以时间分组统计(时间范围.Pre.Start, 时间范围.Pre.End, "week")
	if err != nil {
		return S图表{}, err
	}
	上周单天订单集 := make(map[int]S单天订单)
	for _, item := range 上周单天订单组 {
		idx, _ := strconv.Atoi(item.Day)
		最终序号 := (idx - 1 + 7) % 7
		if dayName, ok := dayMap[最终序号]; ok {
			item.Day = dayName
		}
		上周单天订单集[最终序号] = item
	}

	// 构建周数据（包含上期和当期）
	weekItems := make([]weekItem, 7)
	for i := range 7 {
		defaultItem := S单天订单{Day: dayMap[i], Count: 0, Price: decimal.Zero}
		weekItems[i].Pre = defaultItem
		weekItems[i].Now = defaultItem

		if item, ok := 单天订单集[i]; ok {
			weekItems[i].Now = item
		}
		if item, ok := 上周单天订单集[i]; ok {
			weekItems[i].Pre = item
		}
	}

	data := 提取周数据(weekItems)

	series := []SeriesItem{
		{Name: "上周金额", Type: "bar", ItemStyle: 予蓝色渐变(), Data: data.PrePrices},
		{Name: "本周金额", Type: "bar", ItemStyle: 予绿色渐变(), Data: data.NowPrices},
		{Name: "上周订单数", Type: "line", ItemStyle: 予蓝色渐变(), Data: data.PreCounts, YAxisIndex: 1},
		{Name: "本周订单数", Type: "line", ItemStyle: 予绿色渐变(), Data: data.NowCounts, YAxisIndex: 1},
	}

	// 7. 获取总统计信息
	preTotal, _ := A以时间统计(时间范围.Pre.Start, 时间范围.Pre.End)
	currentTotal, _ := A以时间统计(时间范围.Current.Start, 时间范围.Current.End)
	cycleDiff, _ := 予周期统计差异(preTotal, currentTotal)

	// 8. 组装并返回最终的图表数据结构
	return S图表{
		YAxis:    YAxisData{MaxNum: data.MaxNum, MaxPrice: data.MaxPrice},
		Legend:   []string{"上周金额", "本周金额", "上周订单数", "本周订单数"},
		XAxis:    data.XAxis,
		Series:   series,
		PreCycle: 予上期统计数据(preTotal),
		Cycle:    cycleDiff,
	}, nil
}

var A天组 = []string{
	"01", "02", "03", "04", "05", "06", "07", "08", "09", "10",
	"11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
	"21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31",
}

var A月组 = []string{
	"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12",
}

func (s *S7废留) 予月份() (S图表, error) {
	now := time.Now()
	时间范围 := S时间范围{}
	t本月首天 := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
	t上月首天 := time.Date(now.Year(), now.Month()-1, 1, 0, 0, 0, 0, now.Location())
	t下月首天 := time.Date(now.Year(), now.Month()+1, 1, 0, 0, 0, 0, now.Location())
	本月首天 := t本月首天.Format("2006-01-02")
	// fmt.Printf("本月首天 👉 %+v\n", 本月首天)
	上月首天 := t上月首天.Format("2006-01-02")
	// fmt.Printf("上月首天 👉 %+v\n", 上月首天)
	下月首天 := t下月首天.Format("2006-01-02")
	// fmt.Printf("下月首天 👉 %+v\n", 下月首天)

	时间范围.Pre.Start = 上月首天
	时间范围.Pre.End = 本月首天
	时间范围.Current.Start = 本月首天
	时间范围.Current.End = 下月首天

	return s.双周期统计(
		A天组,
		时间范围,
		"month",
		[]string{"上月金额", "本月金额", "上月订单数", "本月订单数"},
	)
}

func (s *S7废留) 予年份() (S图表, error) {
	时间范围 := S时间范围{}
	now := time.Now()
	currentYear := now.Year() // 获取当前年份

	t去年首天 := time.Date(currentYear-1, time.January, 1, 0, 0, 0, 0, now.Location())
	去年首天 := t去年首天.Format("2006-01-02")
	// fmt.Printf("去年首天 👉 %+v\n", 去年首天)

	t今年首天 := time.Date(currentYear, time.January, 1, 0, 0, 0, 0, now.Location())
	今年首天 := t今年首天.Format("2006-01-02")
	// fmt.Printf("今年首天 👉 %+v\n", 今年首天)

	t明年首天 := time.Date(currentYear+1, time.January, 1, 0, 0, 0, 0, now.Location())
	明年首天 := t明年首天.Format("2006-01-02")
	// fmt.Printf("明年首天 👉 %+v\n", 明年首天)

	时间范围.Pre.Start = 去年首天
	时间范围.Pre.End = 今年首天
	时间范围.Current.Start = 今年首天
	时间范围.Current.End = 明年首天

	return s.双周期统计(
		A月组,
		时间范围,
		"year",
		[]string{"去年金额", "今年金额", "去年订单数", "今年订单数"},
	)
}

func (s *S7废留) 双周期统计(
	dateKeys []string,
	时间范围 S时间范围, cycle string,
	legend []string,
) (S图表, error) {
	// 查询上期和当期数据
	preStart := 时间范围.Pre.Start
	preEnd := 时间范围.Pre.End
	currentStart := 时间范围.Current.Start
	currentEnd := 时间范围.Current.End
	preOrders, _ := A以时间分组统计(preStart, preEnd, cycle)
	currentOrders, err := A以时间分组统计(currentStart, currentEnd, cycle)
	if err != nil {
		return S图表{}, err
	}

	// 转换为map
	preMap := make(map[string]S单天订单, len(preOrders))
	for _, item := range preOrders {
		preMap[item.Day] = item
	}
	currentMap := make(map[string]S单天订单, len(currentOrders))
	for _, item := range currentOrders {
		currentMap[item.Day] = item
	}

	// 填充缺失数据
	preFilled := 补缺失日期(dateKeys, preMap)
	currentFilled := 补缺失日期(dateKeys, currentMap)

	xAxis := make([]string, len(dateKeys))
	prePrices, preCounts := make([]decimal.Decimal, len(dateKeys)), make([]int, len(dateKeys))
	currentPrices, currentCounts := make([]decimal.Decimal, len(dateKeys)), make([]int, len(dateKeys))
	var maxNum int
	var maxPrice decimal.Decimal

	for i, key := range dateKeys {
		xAxis[i] = key // 轴标签使用日期键
		prePrices[i] = preFilled[i].Price
		preCounts[i] = preFilled[i].Count
		currentPrices[i] = currentFilled[i].Price
		currentCounts[i] = currentFilled[i].Count

		// 更新最大值
		currentMaxNum := max(preFilled[i].Count, currentFilled[i].Count)
		if currentMaxNum > maxNum {
			maxNum = currentMaxNum
		}
		currentMaxPrice := a.A予大值(preFilled[i].Price, currentFilled[i].Price)
		if currentMaxPrice.GreaterThan(maxPrice) {
			maxPrice = currentMaxPrice
		}
	}

	// 构建系列
	series := []SeriesItem{
		{Name: legend[0], Type: "bar", ItemStyle: 予蓝色渐变(), Data: prePrices},
		{Name: legend[1], Type: "bar", ItemStyle: 予绿色渐变(), Data: currentPrices},
		{Name: legend[2], Type: "line", ItemStyle: 予蓝色渐变(), Data: preCounts, YAxisIndex: 1},
		{Name: legend[3], Type: "line", ItemStyle: 予绿色渐变(), Data: currentCounts, YAxisIndex: 1},
	}

	// 总统计
	preTotal, _ := A以时间统计(preStart, preEnd)
	currentTotal, _ := A以时间统计(currentStart, currentEnd)
	cycleDiff, _ := 予周期统计差异(preTotal, currentTotal)

	return S图表{
		YAxis:    YAxisData{MaxNum: maxNum, MaxPrice: maxPrice},
		Legend:   legend,
		XAxis:    xAxis,
		Series:   series,
		PreCycle: 予上期统计数据(preTotal),
		Cycle:    cycleDiff,
	}, nil
}

func 予上期统计数据(preTotal *S总计) PreCycleData {
	if preTotal == nil {
		return PreCycleData{
			Count: CycleStat{Data: 0},
			Price: CycleStat{Data: 0},
		}
	}
	return PreCycleData{
		Count: CycleStat{Data: preTotal.Count},
		Price: CycleStat{Data: int(preTotal.Price.IntPart())},
	}
}

type WeekDataResult struct {
	XAxis     []string          // X轴标签（星期几）
	PrePrices []decimal.Decimal // 上期价格数据
	PreCounts []int             // 上期数量数据
	NowPrices []decimal.Decimal // 当期价格数据
	NowCounts []int             // 当期数量数据
	MaxNum    int               // 最大数量
	MaxPrice  decimal.Decimal   // 最大价格
}

func 提取周数据(weekItems []weekItem) *WeekDataResult {
	result := &WeekDataResult{
		XAxis:     make([]string, len(weekItems)),
		PrePrices: make([]decimal.Decimal, len(weekItems)),
		PreCounts: make([]int, len(weekItems)),
		NowPrices: make([]decimal.Decimal, len(weekItems)),
		NowCounts: make([]int, len(weekItems)),
	}

	for i, item := range weekItems {
		result.XAxis[i] = item.Now.Day
		result.PrePrices[i] = item.Pre.Price
		result.PreCounts[i] = item.Pre.Count
		result.NowPrices[i] = item.Now.Price
		result.NowCounts[i] = item.Now.Count

		currentMaxNum := a.A予大值(item.Pre.Count, item.Now.Count)
		if currentMaxNum > result.MaxNum {
			result.MaxNum = currentMaxNum
		}

		currentMaxPrice := a.A予大值(item.Pre.Price, item.Now.Price)
		if currentMaxPrice.GreaterThan(result.MaxPrice) {
			result.MaxPrice = currentMaxPrice
		}
	}
	return result
}

type weekItem struct {
	Pre S单天订单 // 上期数据
	Now S单天订单 // 当期数据
}
